cmake_minimum_required(VERSION 3.13.1 FATAL_ERROR)
# someone might be using cygwin.
# if cygwin isn't used, the next line does nothing
set(CMAKE_LEGACY_CYGWIN_WIN32 0)

enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# project and binary name
project("hms")

message(STATUS "Using Compiler ID "
	${CMAKE_CXX_COMPILER_ID} " v."
	${CMAKE_CXX_COMPILER_VERSION}
)

# compiler specific warnings
# and warnings are treated as errors (for internal builds)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
    "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    set(ALL_WARNINGS_AS_ERRORS -Wall -Wextra -Werror)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
    set(ALL_WARNINGS_AS_ERRORS /W4 /WX /EHsc)
endif()


# default build-type is Debug:
if (NOT CMAKE_BUILD_TYPE)
	set(CMAKE_BUILD_TYPE "Debug")
endif()
# convenience option for building libraries in debug mode
if(CMAKE_BUILD_TYPE MATCHES Debug)
	option(DEBUG_BUILD "Debug build" ON)
endif()
message(STATUS "Build type is " ${CMAKE_BUILD_TYPE} )

# stop compilation at first n errors, to prevent error messsages overflowing
# the command line
# one could also use "make -j$nproc | head --lines x" to only display the
# first x lines.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
	add_compile_options(-fmax-errors=2)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
	add_compile_options(-ferror-limit=2)
endif()

# add -march=native for release builds
if(CMAKE_BUILD_TYPE MATCHES Release)
	include(CheckCXXCompilerFlag)
	CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
	if(COMPILER_SUPPORTS_MARCH_NATIVE)
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
	endif()
endif()



# =============================
# libraries
# =============================

# external

# MPI
message( STATUS "Checking MPI" )
# find_package(MPI)
if (MPI_CXX_FOUND)
	message(STATUS "Checking MPI - found version " ${MPI_CXX_VERSION} )
else()
	message(STATUS "Checking MPI - not found" )
endif()

# OpenMP
message( STATUS "Checking OpenMP" )
find_package(OpenMP)
if (OpenMP_CXX_FOUND)
	message(STATUS "Checking OpenMP - found version " ${OpenMP_CXX_VERSION} )
else()
	message(STATUS "Checking OpenMP - not found" )
endif()

# eigen numerics library (required)
message(STATUS "Checking Eigen library" )
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
set( EIGEN Eigen3::Eigen )
if (${Eigen3_FOUND})
   message(STATUS "Checking Eigen library - found version " ${Eigen3_VERSION} )
   message(STATUS "Eigen library path: " ${Eigen3_DIR} )
else ()
   message(STATUS "Could not locate Eigen library.")
endif()



# =============================
# directory configuration
# =============================

# for finding libraries and such in the project's subdirectories
# all paths are prepended with the project's root directory
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR})

# specifying the output directories below is not strictly necessary,
# when subdirectories are specified with an output directory. 
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# the last one is disabled to allow for tests in a different directory

# project directories
set(INC_DIR ${CMAKE_SOURCE_DIR}/include)
set(LIB_DIR ${CMAKE_SOURCE_DIR}/lib)

include_directories(
	${INC_DIR}
	${LIB_DIR}
)



# =============================
# unit test configuration
# =============================
# enable_testing() sets the internal flag "CMAKE_TESTING_ENABLED" to 1
# add_test() commands are only run when enable_testing() has executed.
# here, it is only executed in debug mode
if(DEBUG_BUILD)
	enable_testing()
endif()


# the unit test framework used here is "Catch2" (single header file "catch.h")
# (https://github.com/catchorg/Catch2)

if ( ${CMAKE_TESTING_ENABLED} )
	message( STATUS "Tests are enabled" )
else()
	message( STATUS "Tests are disabled" )
endif()


# =============================
# subdir calls
# =============================
# if a second parameter is provided, it specifies the output path for binaries.
# however, the respective CMAKE_XYZ_OUTPUT_DIRECTORY takes precedence
add_subdirectory(lib)

add_subdirectory(util)
add_subdirectory(io)
add_subdirectory(mesh)
add_subdirectory(gmsh)
add_subdirectory(solverBase)
add_subdirectory(sweSolver)
add_subdirectory(vtk)
add_subdirectory(verification)
add_subdirectory(rasterReader)
add_subdirectory(settingsImport)

if (MPI_CXX_FOUND)
	add_subdirectory(mpiHelpers)
	add_subdirectory(meshPart)
endif()


add_subdirectory(main ${CMAKE_BINARY_DIR}/bin)

if ( ${CMAKE_TESTING_ENABLED} )
	add_subdirectory(tests tests)
endif()
